package com.atgion.manager.service.impl;

import com.atgion.manager.mapper.*;
import com.atgion.manager.service.AdminArticleService;
import com.atgion.spzx.model.bo.blog.*;
import com.atgion.spzx.model.vo.base.Result;
import com.atgion.spzx.model.vo.blog.*;
import com.atgion.spzx.model.vo.blog.client.QueryArticleDetailRspVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author: 犬小哈
 * @url: www.quanxiaoha.com
 * @date: 2023-04-17 12:08
 * @description: TODO
 **/
@Service
@Slf4j
public class AdminArticleServiceImpl implements AdminArticleService {

    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private ArticleContentMapper articleContentMapper;
    @Autowired
    private ArticleCategoryRelMapper articleCategoryRelMapper;
    @Autowired
    private TagMapper tagMapper;
    @Autowired
    private ArticleTagRelMapper articleTagRelMapper;

    // 手动事务
//    private final TransactionTemplate transactionTemplate;

    @Autowired
    public AdminArticleServiceImpl(PlatformTransactionManager transactionManager) {
        new TransactionTemplate(transactionManager);
    }

    @Override
    @Transactional
    public Result publishArticle(PublishArticleReqVO publishArticleReqVO) {

            ArticleDO articleDO = ArticleDO.builder()
                    .title(publishArticleReqVO.getTitle())
                    .titleImage(publishArticleReqVO.getTitleImage())
                    .description(publishArticleReqVO.getDescription())
                    .build();
            articleMapper.insert(articleDO);

            Long articleId = articleDO.getId();

            ArticleContentDO articleContentDO = ArticleContentDO.builder()
                    .articleId(articleId)
                    .content(publishArticleReqVO.getContent())
                    .build();
            articleContentMapper.insert(articleContentDO);

            // 所属分类
            ArticleCategoryRelDO articleCategoryRelDO = ArticleCategoryRelDO.builder()
                    .articleId(articleId)
                    .categoryId(publishArticleReqVO.getCategoryId())
                    .build();
            articleCategoryRelMapper.insert(articleCategoryRelDO);

            // 标签
            // 提交的标签
            List<String> publishTags = publishArticleReqVO.getTags();
            handleTagBiz(articleId, publishTags);



        return Result.success();
    }

    @Override
    public Result queryArticleDetail(QueryArticleDetailReqVO queryArticleDetailReqVO) {
        Long articleId = queryArticleDetailReqVO.getArticleId();

        QueryWrapper<ArticleDO> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(ArticleDO::getId, articleId).eq(ArticleDO::getIsDeleted, 0);
        ArticleDO articleDO =articleMapper.selectOne(wrapper);

        QueryWrapper<ArticleContentDO> wrapper1 = new QueryWrapper<>();
        wrapper1.lambda().eq(ArticleContentDO::getArticleId, articleId);
        ArticleContentDO articleContentDO =  articleContentMapper.selectOne(wrapper1);

        // 所属分类
        QueryWrapper<ArticleCategoryRelDO> wrapper2 = new QueryWrapper<>();
        wrapper2.lambda().eq(ArticleCategoryRelDO::getArticleId, articleId);
        ArticleCategoryRelDO articleCategoryRelDO = articleCategoryRelMapper.selectOne(wrapper2);

        // 对应标签
        QueryWrapper<ArticleTagRelDO> wrapper3 = new QueryWrapper<>();
        wrapper3.lambda().eq(ArticleTagRelDO::getArticleId, articleId);
        List<ArticleTagRelDO> articleTagRelDOS = articleTagRelMapper.selectList(wrapper3);
        List<Long> tagIds = articleTagRelDOS.stream().map(p -> p.getTagId()).collect(Collectors.toList());

        QueryArticleDetailRspVO queryArticleDetailRspVO = QueryArticleDetailRspVO.builder()
                .id(articleDO.getId())
                .title(articleDO.getTitle())
                .titleImage(articleDO.getTitleImage())
                .content(articleContentDO.getContent())
                .categoryId(articleCategoryRelDO.getCategoryId())
                .tagIds(tagIds)
                .description(articleDO.getDescription())
                .build();

        return Result.success(queryArticleDetailRspVO);
    }

    @Override
    public Result queryArticlePageList(QueryArticlePageListReqVO queryArticlePageListReqVO) {
        Long current = queryArticlePageListReqVO.getCurrent();
        Long size = queryArticlePageListReqVO.getSize();
        LocalDateTime startDate = queryArticlePageListReqVO.getStartDate();
        LocalDateTime endDate = queryArticlePageListReqVO.getEndDate();
        String searchTitle = queryArticlePageListReqVO.getSearchTitle();


        Page<ArticleDO> page = new Page<>(current, size);
        QueryWrapper<ArticleDO> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .like(Objects.nonNull(searchTitle), ArticleDO::getTitle, searchTitle)
                .ge(Objects.nonNull(startDate), ArticleDO::getCreateTime, startDate)
                .le(Objects.nonNull(endDate), ArticleDO::getCreateTime, endDate)
                .orderByDesc(ArticleDO::getCreateTime);
        Page<ArticleDO> articleDOPage =articleMapper.selectPage(page, wrapper);

        return Result.success(articleDOPage);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result deleteArticle(DeleteArticleReqVO deleteArticleReqVO) {
        Long articleId = deleteArticleReqVO.getArticleId();
        articleMapper.deleteById(articleId);
        QueryWrapper<ArticleContentDO> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(ArticleContentDO::getArticleId, articleId);
        articleContentMapper.delete(wrapper);
        return Result.success();
    }

    @Override
     @Transactional(rollbackFor = Exception.class)
    public Result updateArticle(UpdateArticleReqVO updateArticleReqVO) {
            Long articleId = updateArticleReqVO.getId();

            ArticleDO articleDO = ArticleDO.builder()
                    .id(articleId)
                    .title(updateArticleReqVO.getTitle())
                    .titleImage(updateArticleReqVO.getTitleImage())
                    .description(updateArticleReqVO.getDescription())
                    .updateTime(LocalDateTime.now())
                    .build();
            articleMapper.updateById(articleDO);

            ArticleContentDO articleContentDO = ArticleContentDO.builder()
                    .articleId(articleId)
                    .content(updateArticleReqVO.getContent())
                    .build();
            UpdateWrapper<ArticleContentDO> wrapper = new UpdateWrapper<>();
            wrapper.lambda().eq(ArticleContentDO::getArticleId, articleContentDO.getArticleId());
            articleContentMapper.update(articleContentDO, wrapper);

            // 更新文章分类
            QueryWrapper<ArticleCategoryRelDO> wrapper1 = new QueryWrapper<>();
            wrapper1.lambda().eq(ArticleCategoryRelDO::getArticleId, articleId);
            articleCategoryRelMapper.delete(wrapper1);
            ArticleCategoryRelDO articleCategoryRelDO = ArticleCategoryRelDO.builder()
                    .articleId(articleId)
                    .categoryId(updateArticleReqVO.getCategoryId())
                    .build();
            articleCategoryRelMapper.insert(articleCategoryRelDO);

            // 更新文章标签
            QueryWrapper<ArticleTagRelDO> wrapper2= new QueryWrapper<>();
            wrapper2.lambda().eq(ArticleTagRelDO::getArticleId, articleId);
            articleTagRelMapper.delete(wrapper2);
            // 提交的标签
            List<String> publishTags = updateArticleReqVO.getTags();
            handleTagBiz(articleId, publishTags);

        return  Result.success();
    }

    /**
     * 处理标签相关业务
     * @param articleId
     * @param publishTags
     */
    public void handleTagBiz(Long articleId, List<String> publishTags) {
        List<TagDO> tagDOS = tagMapper.selectList(null);

        // 筛选出库中不存在的标签
        List<String> noExistTags = null;
        // 库中已存在的标签
        List<String> existTags = null;
        if (!CollectionUtils.isEmpty(tagDOS)) {
            List<String> tagIds = tagDOS.stream().map(p -> String.valueOf(p.getId())).collect(Collectors.toList());
            noExistTags = publishTags.stream().filter(p -> !tagIds.contains(p)).collect(Collectors.toList());
            existTags = publishTags.stream().filter(p -> tagIds.contains(p)).collect(Collectors.toList());
        }

        // 不存在的标签先入库
        if (!CollectionUtils.isEmpty(noExistTags)) {
            List<ArticleTagRelDO> articleTagRelDOS = Lists.newArrayList();
            noExistTags.forEach(noExistTag -> {
                TagDO tagDO = TagDO.builder()
                        .name(noExistTag)
                        .createTime(LocalDateTime.now())
                        .updateTime(LocalDateTime.now())
                        .build();

                tagMapper.insert(tagDO);
                Long tagId = tagDO.getId();

                ArticleTagRelDO articleTagRelDO = ArticleTagRelDO.builder()
                        .articleId(articleId)
                        .tagId(tagId)
                        .build();
                articleTagRelDOS.add(articleTagRelDO);
            });
            articleTagRelMapper.insertBatchSomeColumn(articleTagRelDOS);
        }

        if (!CollectionUtils.isEmpty(existTags)) {
            List<ArticleTagRelDO> articleTagRelDOS = Lists.newArrayList();
            existTags.forEach(existTagId -> {
                ArticleTagRelDO articleTagRelDO = ArticleTagRelDO.builder()
                        .articleId(articleId)
                        .tagId(Long.valueOf(existTagId))
                        .build();
                articleTagRelDOS.add(articleTagRelDO);
            });
            articleTagRelMapper.insertBatchSomeColumn(articleTagRelDOS);
        }
    }

}
